import asyncio
import urllib
from aiohttp import ClientSession
from queue import Queue
import datetime
import json
import logging
# from aiofiles import open

DATAFMT = "%Y/%m/%d-%H:%M:%S"
FORMAT = "%(lineno)d %(asctime)s   %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT, datefmt=DATAFMT)


class Music:

    def dict_get(self, d: dict, fields: list = None):
        if not fields:
            return d.keys()
        return (d.get(k, "") for k in d.keys() if k in fields)

    def __init__(self, name, type_str, n):
        self.number = n
        self.name = name
        self.type_str = type_str
        self.url = "https://music.liuzhijin.cn"
        self.q1 = Queue()
        self.q2 = Queue()
        self.i = 0

        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36",
            "Origin": "https://music.liuzhijin.cn",
            "Referer": f"https://music.liuzhijin.cn/?name={urllib.parse.quote(name)}&type={type_str}",
            "x-requested-with": "XMLHttpRequest",
            "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
        }

        # self.task = asyncio.create_task(self._post())
        self.collection_page()

    def loop(self):
        while True:
            yield

    async def post(self, number):
        # # print("in post")
        for _ in self.loop():
            if self.q1.empty():
                print("所有的东西都放入q2里了")
                return
            page = self.q1.get()
            items = {"input": self.name,
                     "filter": "name",
                     "type": self.type_str,
                     "page": page}
            # print("post 1")
            async with ClientSession(headers=self.headers) as session:  # 不会进行协程切换
                # print("post 2")
                print("post已经发送请求，等待响应，进行切换")
                async with session.post(url=self.url, data=items) as resp:  # 会进行协程切换
                    # 如果干好了，往下走，没干好，老板也不在这待着，继续走，
                    # print("post 3")
                    print("得到响应了 post")
                    res = json.loads((await resp.content.read()).decode())  # 不会切换
                    # print("post 4")
                    # print(res["data"], len(res["data"]))
                    for m in res["data"]:
                        print("往q2里放东西")
                        self.q2.put(self.dict_get(m, ["songid", "title", "author", "url"]))  # q2里边放的是url, title, songid
                    # await asyncio.sleep(0)  # 老板走了，去别处看看

    def get_data(self):
        if self.q2.empty():
            raise Exception("self.q2 is empty~~~~")
        res_post = self.q2.get()  # 一个三元组
        return res_post

    def collection_page(self):
        for page in range(1, self.number + 1):
            self.q1.put(page)

    async def download(self):
        # setattr(self, "session", ClientSession(headers=self.headers))
        start = datetime.datetime.now()
        tasks = [
            self.post, self._download, self._download, self._download, self._download,
            # self.post, self._download, self._download
            # self.post, self._download, self._download, self._download, self._download, self._download, self._download,
            # self.post, self._download, self._download, self._download, self._download, self._download, self._download,
        ]

        tasks = [asyncio.create_task(task(i)) for i, task in enumerate(tasks)]
        await asyncio.gather(*tasks)
        end = datetime.datetime.now()
        print((end - start).total_seconds())
        print("end")
        print(self.q1.empty(), self.q2.empty())

    async def _download(self, number):
        # print("_download 1")

        # await asyncio.sleep(0)  # 切换
        while not (self.q1.empty() and self.q2.empty()):  # 开始的时候一定不是空的
            # 开始的时候一定是空的，没法干活，老板过来看了一圈就走了，让干活的先歇0.5S，老板直接走，基本不会在这占用时间
            while self.q2.empty():  # 老板来了，看看你睡够了吗，如果睡够了，你在看看需要用的东西有了没，没有继续睡觉，老板去别处
                # print("q2目前还没东西， 先睡1.5秒  切换", number)
                await asyncio.sleep(1.5)
            # 倒着说明东西有了，开始干活吧
            # print("_download 2")
            try:
                print("q2 不空，可以干活了", number)
                songid, title, author, url = self.q2.get()
                if url:
                    async with ClientSession(headers=self.headers) as session:
                        # print("_download 3")
                        url: str = url
                        print("download 中去请求下载歌曲， 进行切换", number)
                        async with session.get(url) as resp:  # 会切换,工人在此处干活，老板去别处逛
                            # print("_download 4")
                            print("得到歌曲的响应了, 准备写入到本地  切换", number)
                            content = await resp.content.read()  # 会切换，取得最后的值，老板去别处逛
                            # print("_download 5")
                            print("download", number, "得到响应了，正在写入本地-----------同步")
                            with open(f"./md/{title}{songid}{author}.{url.rpartition('.')[-1]}", 'wb')as f:
                                # for chunk in res.iter_content(1024*200):
                                f.write(content)
                                self.i += 1
                                print(f"正在下载{self.i}@@@{title}{songid}")
                            # await session.close()
            except Exception as e:
                # print(e, 11111111111111111111)
                logging.info(e)
        # # print("_download end")

    def run(self):
        asyncio.run(self.download())


# name = input("请输入要下载的音乐名\n")
# number = int(input("请输入要下载的个数，默认5-10个，你输入几，就是几*(x-10)个\n"))
# 35.960782  31.104783

name = "陈奕迅"
number = 5
music = Music(name, "netease", number)
music.run()
